package com.crazymakercircle.imServer.server;

import com.crazymakercircle.im.common.bean.User;
import com.crazymakercircle.imServer.distributed.OnlineCounter;
import com.crazymakercircle.imServer.redisDao.SessionRemoteDAO;
import com.crazymakercircle.imServer.redisDao.UserSessionsDAO;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Data
@Repository("SessionManger")
public  class SessionManger {

    @Autowired
    SessionRemoteDAO sessionRedisCashe;

    @Autowired
    UserSessionsDAO userRedisCashe;



    private static SessionManger singleInstance = null;

    //会话集合
    private ConcurrentHashMap<String, LocalSession> localMap =
            new ConcurrentHashMap<String, LocalSession>();

    public static SessionManger inst() {
        return singleInstance;
    }

    public static void setSingleInstance(SessionManger singleInstance) {
        SessionManger.singleInstance = singleInstance;
    }

    /**
     * 增加session对象
     */
    public void addSession(
            String sessionId, LocalSession s) {
        localMap.put(sessionId, s);
        log.info("用户登录:id= " + s.getUser().getUid()
                + "   在线总数: " + localMap.size());

        String uid = s.getUser().getUid();

        //增加用户数
        OnlineCounter.getInst().increment();

        //分布式保存user和所有session
        sessionRedisCashe.casheRemoteSession(uid, sessionId);
        userRedisCashe.casheUser(uid, sessionId);
    }

    /**
     * 根据用户id，获取session对象
     */
    public List<ServerSession> getSessionsBy(String userId) {

        Set<String> sids =
                userRedisCashe.getAllSessionId(userId);

        List<ServerSession> oSessions = new LinkedList<>();
        Iterator<String> i = sids.iterator();
        while (i.hasNext()) {
            String sid = i.next();

            ServerSession s;
            if (localMap.contains(sid)) {
                s = localMap.get(sid);
            } else {
                s = sessionRedisCashe.get(sid);
            }
            oSessions.add(s);
        }
        return oSessions;

    }

    /**
     * 删除session
     */
    public void removeSession(String sessionId) {
        if (!localMap.containsKey(sessionId)) {
            return;
        }
        LocalSession s = localMap.get(sessionId);
        String uid = s.getUser().getUid();
        localMap.remove(sessionId);


        //减少用户数
        OnlineCounter.getInst().decrement();

        //分布式保存user和所有session
        sessionRedisCashe.removeRemote(uid, sessionId);
        userRedisCashe.removeUserSession(uid, sessionId);


    }

    /**
     * 判断用户是否登录
     *
     * @param user 用户
     * @return 登录状态
     */
    public boolean hasLogin(User user) {
        List<ServerSession> l = getSessionsBy(user.getUid());
        if (null != l && l.size() > 0) {
            return true;
        }

        return false;
    }



    //关闭连接
    public  void closeSession(ChannelHandlerContext ctx) {

        LocalSession session =
                ctx.channel().attr(LocalSession.SESSION_KEY).get();

        if (null != session && session.isValid()) {
            session.close();
          this.removeSession(session.getSessionId());
        }
    }

    //和channel 通道实现双向绑定
    public LocalSession bind(LocalSession session) {
        session.bind();

        this.addSession(session.getSessionId(), session);
        return session;
    }


    public LocalSession unbind(LocalSession session) {

        session.unbind();

        this.removeSession(session.getSessionId());

        return session;
    }
}
